# MCP Server工具 - HTTP Stream 类 MCP Server
import sys
import re
from pathlib import Path
project_root = Path(__file__).resolve().parent.parent.parent.parent
sys.path.insert(0, str(project_root))
import os
import json
import asyncio
import pymysql
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP
from insight_agent.utils.http_post import get_insight_request, inform_insight_thinking, update_insight_result
from insight_agent.utils.agent_generator import AgentGenerator
from langchain_core.tools import tool


# ============================ 全局配置 ============================
# 加载环境变量
load_dotenv(override=True)
# 加载Agent所需大模型
llm_model_name = os.getenv("LLM_MODEL")
# 获取当前文件的目录
current_dir = Path(__file__).resolve().parent
# 加载Agent所需提示词
prompts_file_path = current_dir / 'agent_map_prompt.txt'
# 加载Agent所需工具配置
servers_config_path = current_dir / 'agent_map_servers_config.json'
# 配置线程
thread_config_1 = {"configurable": {"thread_id": "thread1"}}

# 加载Agent生成器
agent_generator = AgentGenerator()
# 初始化 Insight Agent
agent_map_instance = asyncio.run(agent_generator.create_agent(llm_model_name,
                                                              prompts_file_path,
                                                              servers_config_path))
host = os.getenv('HOST')
user = os.getenv('USER')
mysql_pw = os.getenv('MYSQL_PW')
db = os.getenv('DB_NAME')
port = os.getenv('PORT')

fields_mapping = {
    "LABEL_IS_GSM": "gsmCustCount",
    "LABEL_IS_MID": "waistCustCount",
    "LABEL_IS_PREM": "premiumCustCount",
    "LABEL_IS_DIFF": "diffNetUserCount",
    "LABEL_IS_ELDER": "shairUserCnt",
    "LABEL_IS_INT": "internationalUserCnt",
    "ATTR_FAMILY_CIRCLE_ID": "familyCircleCnt",
    "ATTR_COMMUTE_CIRCLE_ID": "commuteCircleCnt",
    "ATTR_SOCIAL_CIRCLE_ID": "socialCircleCnt",
    "ATTR_CAMPUS_CIRCLE_ID": "campusCircleCnt"
}

# ============================ MCP服务 ============================
# 定义 MCP Server
mcp = FastMCP("agent_map", port=5129)

@mcp.tool()
async def agent_map(user_request):
    '''
    仅当用户提到与“地图、网格、地理位置、区域、地区、地图上的分布、地理位置上的分布”相关的问题时使用本工具
    :param user_request: 用户的相关输入
    :return: 使用本工具的总结回复
    '''
    # 通过 MCP 获取 main_agent 转发的内容
    print(f'💡子智能体 agent_map 通过MCP 收到用户请求：{user_request}')
    post_response = inform_insight_thinking("agent_map", f'好的，用户希望{user_request}')

    #  获取待推送给 main_agent 的 data
    sql_query = await generate_sql(user_request)
    print(f'💡子智能体 agent_map 根据用户输入生成了数据查询语句 {sql_query}')
    post_response = inform_insight_thinking("agent_map", f'根据用户输入生成了数据查询语句 {str(sql_query)[:20]}...')

    sql_results = await inquire_data(sql_query)
    print(f'💡子智能体 agent_map 根据数据查询语句得到查询结果 {sql_results}')
    post_response = inform_insight_thinking("agent_map", f'根据数据查询语句得到{len(sql_results)}条查询结果并聚合到网格')

    # 获取待推送给 main_agent 的 data
    field, data_to_post = await format_data(sql_query, sql_results)
    print(f'💡子智能体 agent_map 将查询结果整理成前端展示接口的形式：{str(data_to_post)[:20]}...{field}... ')
    post_response = inform_insight_thinking("agent_map", f'将查询结果整理成前端展示接口的形式：{str(data_to_post)[:20]}...{field}... ')

    #  获取待推送给 main_agent 的 summary
    summary_to_post = await generate_summary(data_to_post)
    print(f'💡子智能体 agent_map 根据查询结果生成了数据总结报告 {summary_to_post}')
    post_response = inform_insight_thinking("agent_map", f'根据查询结果生成了数据总结报告：{str(summary_to_post)[:20]}')

    # 汇总准备推送给 main_agent 的信息 {"summary": summary, "data": data}
    updated_result = combine_info_to_post(summary_to_post, data_to_post)
    # 通过 POST 的方式更新 main_agent 的 insight_result
    post_response = update_insight_result("agent_map", updated_result)  # 向 insight_result 中更新 agent_map 相关的洞察结果
    print(f'💡子智能体 agent_map 向 main_agent 推送数据获得响应：{post_response}')

    # return updated_result["summary"]
    return summary_to_post


async def generate_sql(user_request: str):
    '''
    当用户需要将输入转换为SQL语句时使用
    :param user_request: 需要转换为SQL语句的自然语言输入
    :return:
    '''
    result = await agent_map_instance.ainvoke(
        {"messages": [{"role": "system",
                       "content":
                           f'''请将“{user_request}”根据背景知识转换为转换为字符串形式的SQL语句，不要Markdown形式，不要添加任何其他额外内容和字符'''}]},
        thread_config_1
    )
    sql_query = result['messages'][-1].content
    return sql_query


async def inquire_data(sql_query: str):
    """
    当用户需要进行数据库查询工作时，请调用该函数。
    该函数用于在指定MySQL服务器上运行一段SQL代码，完成数据查询相关工作，
    并且当前函数是使用pymsql连接MySQL数据库。
    :param sql_query: 字符串形式的SQL查询语句，用于执行对MySQL数据库中insight_general_table表进行查询，并获得相关信息
    :return：sql_query在MySQL中的运行结果。
    """
    # 创建连接
    connection = pymysql.connect(
        host=host,
        user=user,
        passwd=mysql_pw,
        db=db,
        port=int(port),
        charset='utf8'
    )
    try:
        with connection.cursor() as cursor:
            cursor.execute(sql_query)
            sql_results = cursor.fetchall()
            print(f"💡查询结果{str(sql_results)[:30]}")
    finally:
        connection.close()

    # 将结果以 JSON 字符串形式返回
    return sql_results


def extract_conditions(sql_query):
    """ 从SQL查询语句中提取WHERE条件里 = 1 或 = 0 的条件 """
    # 找到WHERE子句
    where_match = re.search(r'WHERE\s+(.*?)(?=\s+GROUP BY|\s+ORDER BY|\s+HAVING|\s+LIMIT|$)', sql_query, re.IGNORECASE)
    if not where_match:
        return []
    where_clause = where_match.group(1)
    # 提取 = 1 或 = 0 的条件
    conditions = re.findall(r'(\w+)\s*=\s*(0|1)(?:\s+AND|\s+OR|$)', where_clause, re.IGNORECASE)
    # 格式化结果
    result = [f"{field} = {value}" for field, value in conditions]
    return result


async def format_data(sql_query, sql_results):
    conditions = extract_conditions(sql_query)
    field = fields_mapping[conditions[0].split(' ')[0]]

    grids_list = []
    data_to_post = {
        "gridsList": grids_list
    }
    for result in sql_results:
        grids_list.append({
            "statisTime": result[0],
            "provId": result[1],
            "gridId": result[2],
            "gridLongitude": result[3],
            "gridLatitude": result[4],
            field: result[5]
        })
    return field, data_to_post


async def generate_summary(data_to_post) -> str:
    '''
    根据数据 data_to_post 形成一篇200字的Markdown形式的报告
    :param data_to_post: 转换形式后的MySQL查询结果
    :return: 200字的Markdown形式的报告
    '''
    result = await agent_map_instance.ainvoke(
        {"messages": [{"role": "system",
                       "content": f'''请将“{data_to_post}”总结成一段200字左右的的Markdown形式的报告'''}]},
        thread_config_1
    )
    summary = result['messages'][-1].content
    # 处理 summary
    summary_to_post = summary.replace('markdown', '').replace('```', '')
    return summary_to_post


def combine_info_to_post(summary: str, data: dict):
    updated_result =  {
        "summary": summary,
        "data": data
    }
    return updated_result



if __name__ == "__main__":
    mcp.run(transport="streamable-http")
    '''
    地图数据供给，解析 insight_json 中 Map.metrics 对应的值，将其转为可查询的SQL查询语句sql_query，
    比如 Map.metrics 中有 LABEL_IS_GSM 和 ATTR_SOCIAL_CIRCLE_ID 两个元素，
    则生成 SELECT ATTR_GRID_ID, COUNT(LABEL_IS_GSM), COUNT(DISTINCT(ATTR_COMMUTE_CIRCLE_ID)) FROM insight_general_table GROUP BY ATTR_GRID_ID;
    然后使用 sql_inquire 查询并整理成 [{"ATTR_GRID_ID": "", "IS_GSM_COUNT": "", "COMMUTE_CIRCLE_COUNT": ""}] 的形式返回
    :return: insight_json 洞察核心
    '''
    # user_request = '你好'
    # grab_grid_info(user_request)
    #
    # updated_result = asyncio.run(summarize_info(user_request))







